﻿using System;
using System.Collections.Generic;
using System.Text;
using Wangzeran.CodeMaker.Core.Tag;
using Wangzeran.CodeMaker.Core.Template;
using Wangzeran.CodeMaker.PlugIns.Templates;
using Wangzeran.CodeMaker.Core.Model;

namespace Wangzeran.CodeMaker.PlugIns.Tags
{
    /// <summary>
    /// Foreach标签
    /// </summary>
    public class ForeachTag : TagSupport
    {

        #region 标签属性字段

        /// <summary>
        /// 循环类型
        /// </summary>
        private const string ATTR_ITEM = "item";
        /// <summary>
        /// 循环次数
        /// </summary>
        private const string ATTR_TIMES = "times";
        /// <summary>
        /// 起始索引
        /// </summary>
        private const string ATTR_STARTINDEX = "startIndex";
        /// <summary>
        /// 循环长度
        /// </summary>
        private const string ATTR_LENGTH = "length";

        #endregion

        /// <summary>
        /// 模板
        /// </summary>
        private ITemplate template = null;

        #region TagSuport成员
        /// <summary>
        /// 标记名称
        /// </summary>
        public override string TagName
        {
            get { return "c:foreach"; }
        }
        /// <summary>
        /// 标签处理
        /// </summary>
        /// <param name="tagStr">标签文本</param>
        /// <returns></returns>
        public override string Process(string tagStr, object value)
        {
            try
            {
                return this.ProcessTag(tagStr, value);
            }
            catch (Exception ex)
            {	
                throw ex;
            }
        }
        /// <summary>
        /// 处理标签
        /// </summary>
        /// <param name="tagStr">标签文本</param>
        /// <param name="value">标签值</param>
        /// <returns></returns>
        public override string ProcessTag(string tagStr, object value)
        {
            try
            {
                string[] lines =
                        tagStr.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);

                if (lines.Length < 3)
                {
                    return String.Empty;
                }

                // 初始化属性
                InitProperties(lines[0]);
                // 获取循环内容
                string contents = GetTagContents(lines);
                // 循环结果
                string result = ProcessProperty(contents, value);

                return result;
            }
            catch (Exception ex)
            {	
                throw ex;
            }
        }

        #endregion


        #region 私有方法

        /// <summary>
        /// 获取标签内容
        /// </summary>
        /// <param name="lines"></param>
        /// <returns></returns>
        private string GetTagContents(string[] lines)
        {
            try
            {
                StringBuilder sbContents = new StringBuilder();
                for (int i = 1; i < lines.Length - 2; i++)
                {
                    sbContents.AppendLine(lines[i]);
                }
                sbContents = sbContents.Remove(sbContents.Length - 2, 2);
                return sbContents.ToString();
            }
            catch (Exception ex)
            {	
                throw ex;
            }
        }

        /// <summary>
        /// 处理属性
        /// </summary>
        /// <param name="contents">循环文本</param>
        /// <param name="value">标签值</param>
        /// <returns></returns>
        private string ProcessProperty(string contents, object value)
        {
            try
            {
                string result = String.Empty;
                if (this.Properties.ContainsKey(ATTR_ITEM))
                {
                    switch (this.Properties[ATTR_ITEM])
                    {
                        case "column":
                            {
                                if (value is TableModal)
                                {
                                    result = ProcessColumn(contents, value as TableModal);
                                }
                                break;
                            }
                        case "table":
                            {
                                if (value is TableModal)
                                {
                                    result = ProcessTable(contents, value as TableModal);
                                }
                                break;
                            }
                        case "text":
                            {
                                result = ProcessText(contents);
                                break;
                            }
                        default:
                            {
                                break;
                            }
                    }
                }
                return result;
            }
            catch (Exception ex)
            {	
                throw ex;
            }
        }

        /// <summary>
        /// 处理列
        /// </summary>
        /// <param name="contents">循环内容</param>
        /// <param name="table">表实体</param>
        /// <returns></returns>
        private string ProcessColumn(string contents, TableModal table)
        {
            try
            {
                string fileName = null;
                StringBuilder sb = new StringBuilder();
                template = new ForeachColumnTemplate();
                int length = table.Columns.Count;
                int startIndex = 0;
                if (this.Properties.ContainsKey(ATTR_LENGTH))
                {
                    Int32.TryParse(this.Properties[ATTR_LENGTH], out length);
                }
                if (this.Properties.ContainsKey(ATTR_STARTINDEX))
                {
                    Int32.TryParse(this.Properties[ATTR_LENGTH], out startIndex);
                }
                int count = 0;
                foreach (ColumnModal column in table.Columns.Values)
                {
                    if (count >= length)
                    {
                        break;
                    }
                    count++;
                    if (count < startIndex)
                    {
                        continue;
                    }
                    string result = template.ExecuteTempldateContents(null, contents, column, out fileName);
                    if (result.Length == 0)
                    {
                        continue;
                    }
                    sb.AppendLine(result);
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {	
                throw ex;
            }
        }

        /// <summary>
        /// 处理表
        /// </summary>
        /// <param name="contents">循环内容</param>
        /// <param name="table">表实体</param>
        /// <returns></returns>
        private string ProcessTable(string contents, TableModal table)
        {
            try
            {
                string fileName = null;
                StringBuilder sb = new StringBuilder();
                template = new ForeachTableTemplate();

                foreach (TableModal extraTable in table.ExtraTable.Values)
                {
                    string result = template.ExecuteTempldateContents(null, contents, extraTable, out fileName);
                    if (result.Length == 0)
                    {
                        continue;
                    }
                    sb.AppendLine(result);
                }

                return sb.ToString();
            }
            catch (Exception ex)
            {	
                throw ex;
            }
        }

        /// <summary>
        /// 处理文本
        /// </summary>
        /// <param name="contents">循环内容</param>
        /// <returns></returns>
        private string ProcessText(string contents)
        {
            try
            {
                string fileName = null;
                StringBuilder sb = new StringBuilder();
                int times = this.Properties.ContainsKey(ATTR_TIMES) ?
                    Convert.ToInt32(this.Properties[ATTR_TIMES]) : 1;
                for (int i = 0; i < times; i++)
                {
                    string result = template.ExecuteTempldateContents(null, contents, null, out fileName);
                    sb.AppendLine(result);
                }

                return sb.ToString();
            }
            catch (Exception ex)
            {	
                throw ex;
            }
        }

        #endregion

        
    }
}
